package com.caits.lbs.framework.utils;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSON;
import com.caits.lbs.framework.Constants.Common;
import com.caits.lbs.framework.bean.common.ApiParam;
import com.caits.lbs.framework.bean.common.ApiResult;

public class JsonUtilAlibaba {

	private static Logger logger = LoggerFactory.getLogger(JsonUtilAlibaba.class);

	/**
	 * 将给定的源对象转换为Json字符串
	 * 
	 * @param src
	 * @return
	 */
	public static String getJsonString(Object src) {

		if (src == null) {
			return null;
		}

		return JSON.toJSONString(src);
	}

	/**
	 * 将给定的Json字符串转换为源对象
	 * 
	 * @param <T>
	 * 
	 * @param src
	 * @return
	 */
	public static <T> T getObjFromJson(String src, Class<T> cls) {
		if (src == null || cls == null) {
			return null;
		}

		return JSON.parseObject(src, cls);
	}

	/**
	 * 将传递过来的jsonString字符串转换为ApiResult对象
	 * 
	 * @param jsonString
	 * @return
	 */
	public static ApiResult getApiResult(String jsonString) {
		ApiResult apiResult = null;
		try {
			if (jsonString != null) {
				apiResult = JSON.parseObject(jsonString, ApiResult.class);
			}
		} catch (Exception e) {
			logger.error(Common.BASE000005, e);
		}
		return apiResult;
	}

	/**
	 * 将传递过来的param字符串转换为对象
	 * 
	 * @param jsonParam
	 * @return
	 */
	public static <T> ApiParam<T> getApiParam(String jsonParam) {
		ApiParam<T> result = null;
		try {
			result = JSON.parseObject(jsonParam, ApiParam.class);
		} catch (Exception e) {
			logger.error(Common.BASE000005, e);
		}
		return result;
	}

	/**
	 * 将传递过来的param字符串转换为对象
	 * 
	 * @param jsonParam
	 * @return
	 */
	public static <T> ApiParam<T> getApiParam(String jsonParam, Class<?> clazz) {
		ApiParam<T> result = null;
		try {
			Type objectType = type(ApiParam.class, clazz);
			result = JSON.parseObject(jsonParam, objectType);
		} catch (Exception e) {
			logger.error(Common.BASE000005, e);
		}
		return result;
	}
	//////////////////////////////////////////////////////////////////////////////////////
	// typeCaches 用于缓存带解析对象的类型.
	// 缓存池已经通过校验,
	private static final ConcurrentMap<Type, ConcurrentMap<Type, ParameterizedType>> typeCaches = new ConcurrentHashMap<Type, ConcurrentMap<Type, ParameterizedType>>();

	private static final ParameterizedType getCachedType(final Type raw, final Type arg) {
		ConcurrentMap<Type, ParameterizedType> map = checkAndGetRawEntry(raw);
		return checkAndGetType(map, raw, arg);
	}

	private static final ParameterizedType checkAndGetType(final ConcurrentMap<Type, ParameterizedType> map,
			final Type raw, final Type arg) {
		ParameterizedType type = map.get(arg);
		if (type == null) {
			map.putIfAbsent(arg, createType(raw, arg));
			type = map.get(arg);
		}
		return type;
	}

	private static final ConcurrentMap<Type, ParameterizedType> checkAndGetRawEntry(final Type raw) {
		ConcurrentMap<Type, ParameterizedType> map = typeCaches.get(raw);
		if (map == null) {
			typeCaches.putIfAbsent(raw, new ConcurrentHashMap<Type, ParameterizedType>());
			map = typeCaches.get(raw);
		}
		return map;
	}

	private static ParameterizedType createType(final Type raw, final Type arg) {

		return new ParameterizedType() {
			public Type getRawType() {
				return raw;
			}

			public Type[] getActualTypeArguments() {
				return new Type[] { arg };
			}

			public Type getOwnerType() {
				return null;
			}
		};
	}

	private static ParameterizedType type(final Type raw, final Type arg) {
		return getCachedType(raw, arg);
	}

	static ParameterizedType type(final Class<?> raw, final Type... args) {
		return new ParameterizedType() {
			public Type getRawType() {
				return raw;
			}

			public Type[] getActualTypeArguments() {
				return args;
			}

			public Type getOwnerType() {
				return null;
			}
		};
	}

	/**
	 * 验证MD5
	 * 
	 * @param json
	 *            Json字符串
	 * @param signValue
	 *            从Parameter对象中取出的签名字符串
	 * @return
	 */
	public static boolean validateSign(String json, String signValue, String authKey) {
		boolean result = false;
		try {
			// 将签名字符串替换为签名KEY
			String sourceStr = json.replaceAll(signValue, authKey);
			// MD5加密
			String md5Str = MD5.encode(sourceStr);
			// 比较MD5字符串
			result = (md5Str.equalsIgnoreCase(signValue));
		} catch (Exception e) {
			logger.error(Common.BASE000002, e);
		}
		return result;
	}
}
